# -*- coding: utf-8 -*-
#	Copyright 2005,2006,2007,2008 Spike^ekipS <spikeekips@gmail.com>
#
#	   This program is free software; you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation; either version 2 of the License, or
#	(at your option) any later version.
#
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#
#	You should have received a copy of the GNU General Public License
#	along with this program; if not, write to the Free Software
#	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

try :
	import lucene
	env = lucene.initVM(lucene.CLASSPATH)
except :
	raise ImportError, "Install pyLucene."

import os, datetime
import pylucene

FIELD_NAME_UID		= "__uid__"
FIELD_NAME_PK		= "__pk__"
FIELD_NAME_MODEL	= "__model__"

class DocumentObject (dict) :
	def __init__ (self, model, doc, queryset=None, ) :
		self.doc = doc
		self.fields = get_fields_from_model(model)

		_r = list()
		for f in self.fields :
			ff = doc.getField(f.name)
			if ff is None :
				continue
			_r.append(
				(
					f.name,
					get_value_index_to_object(f, ff.stringValue(), queryset=queryset),
				)
			)

		for i in (FIELD_NAME_UID, FIELD_NAME_PK, FIELD_NAME_MODEL) :
			_r.append(
				(
					i,
					get_value_index_to_object(i, doc.getField(i).stringValue())
				)
			)

		self.update(_r)

	def __getitem__ (self, k) :
		if self.has_key(k) :
			return self.get(k)
		elif self.doc.get(k, None) :
			return self.doc.get(k, None)

		raise KeyError, k

	def __unicode__ (self) :
		return "<DocumentIndexed: %s>" % self.get("__pk__")

def get_fields_from_model (model) :
	try :
		__fields = model._meta.fields_index
	except AttributeError :
		__fields = list()

	if len(__fields) < 1 :
		__fields = list()
		for f in model._meta.fields :
			__fields.append(f.name)

	return [model._meta.get_field(i) for i in list(set(__fields))]

def translate_datetime_to_str (dt) :
	return dt.strftime("%Y%m%d%H%M%S")

def translate_str_to_datetime (dt, kind=None) :
	d = datetime.datetime.strptime(dt, "%Y%m%d%H%M%S")
	if kind :
		_y, _m, _d = d.year, d.month, d.day
		if kind == "year" :
			_m, _d, = 1, 1
		elif kind == "month" :
			_d = 1

		return datetime.date(_y, _m, _d)
	else :
		return d

def get_value_object_to_index (f_type, value) :
	if type(value) in (list, tuple, ) :
		return [get_value_object_to_index(f_type, i) for i in value]

	if f_type.__class__ in pylucene.FIELDS_STR :
		return value
	elif f_type.__class__ in pylucene.FIELDS_INT :
		return str(value)
	elif f_type.__class__ in pylucene.FIELDS_DATE :
		if isinstance(value, datetime.datetime) :
			return translate_datetime_to_str(value)
		else :
			return str(value)
	elif f_type.__class__ in pylucene.FIELDS_META :
		return value
	elif f_type.__class__ in pylucene.FIELDS_PATH :
		if type(value) in (str, unicode, ) :
			values = list()
			subpaths = [i for i in value.split(os.sep)]
			for i in xrange(len(subpaths)) :
				values.append("/".join(subpaths[:i+1]))
			return values
		else :	
			return value
	else :
		return value

def get_value_index_to_object (f_type, value, queryset=None) :
	if type(f_type) in (str, unicode, ) and f_type == FIELD_NAME_PK :
		return int(value)
	elif type(f_type) in (str, unicode, ) and f_type in (FIELD_NAME_MODEL, FIELD_NAME_UID) :
		return value
	elif f_type.__class__ in pylucene.FIELDS_STR :
		return value
	elif f_type.__class__ in pylucene.FIELDS_INT :
		return int(value)
	elif f_type.__class__ in pylucene.FIELDS_DATE :
		if hasattr(queryset, "_kind") and queryset._kind :
			return translate_str_to_datetime(value, queryset._kind)
		else :
			return translate_str_to_datetime(value)
	elif f_type.__class__ in pylucene.FIELDS_META :
		return value
	elif f_type.__class__ in pylucene.FIELDS_PATH :
		return value
	else :
		return value

def flatten_indexed_value (f_type, value) :
	if f_type.__class__ in pylucene.FIELDS_STR :
		return get_value_object_to_index(f_type, value)
	elif f_type.__class__ in pylucene.FIELDS_INT :
		return get_value_object_to_index(f_type, value)
	elif f_type.__class__ in pylucene.FIELDS_DATE :
		return get_value_object_to_index(f_type, value)
	elif f_type.__class__ in pylucene.FIELDS_META :
		return value
	elif f_type.__class__ in pylucene.FIELDS_PATH :
		return value
	else :
		return value

def get_model_name (model) :
	return "%s.%s" % (model._meta.app_label, model._meta.verbose_name)

def get_uid (model, pk) :
	return "%s/%s" % (get_model_name(model), pk, )

def get_object_uid (obj) :
	return get_uid(obj, obj.pk)

def create_field (field, value, store=True, tokenize=True, add_sort=False, ) :
	__terms = list()
	if not value :
		__terms.append((value, True, False,))
	else :
		v = get_value_object_to_index(field, value)
		if type(v) in (str, unicode, ) :
			__terms.append((v, store, tokenize,))
		elif type(v) in (list, tuple, ) :
			for i in v :
				if i.strip() :
					__terms.append((i, True, False,))

	terms = list()
	for i in __terms :
		terms.append(
			lucene.Field(
				field.name,
				i[0],
				i[1] and lucene.Field.Store.YES or lucene.Field.Store.NO,
				i[2] and lucene.Field.Index.TOKENIZED or lucene.Field.Index.UN_TOKENIZED,
			)
		)

	# add sorting field
	if __terms and add_sort :
		terms.append(
			lucene.Field(
				"sort__%s" % field.name,
				flatten_indexed_value(field, value),
				lucene.Field.Store.YES,
				lucene.Field.Index.UN_TOKENIZED,
			)
		)

	return terms

######################################################################
# signals
def func_pre_save (instance=None, sender=None, created=False, **kwargs) :
	pass

def func_post_save (instance=None, sender=None, created=False, **kwargs) :
	pylucene.Indexer(instance, ).index().close()

def func_pre_delete (instance=None, sender=None, **kwargs) :
	pass

def func_post_delete (instance=None, sender=None, **kwargs) :
	pylucene.Indexer(instance, ).unindex()

MODELS_REGISTERED = dict()
def register_model (model) :
	from django_searcher.lucene_to_django_model.models import manager as manager_lucene

	MODELS_REGISTERED.update(
		{
			get_model_name(model): model,
		}
	)
	model.objects_search = manager_lucene.SearchManager()
	model.objects_search.contribute_to_class(model, "objects_search")

register = register_model



"""
Description
-----------


ChangeLog
---------


Usage
-----


"""

__author__ =  "Spike^ekipS <spikeekips@gmail.com>"




